package com.generator.demo.utils.generatorUtil;

import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.type.JdbcType;

import java.math.BigDecimal;
import java.sql.*;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

@Slf4j
public class DBHelper {

    private final static String URL = "jdbc:mysql://localhost:3306/test?serverTimezone=Asia/Shanghai&useUnicode=true&characterEncoding=utf-8&zeroDateTimeBehavior=convertToNull&useSSL=false&allowPublicKeyRetrieval=true";
    private final static String USER = "root";
    private final static String PASSWORD = "root";
    private final static String DRIVER = "com.mysql.cj.jdbc.Driver";
    private final static String DATABASE = "test";
    private final static String CREATE_USER = "fxh";

    private static Connection getConnection() {
        Connection connection = null;
        try {
            Class.forName(DRIVER);
            connection = DriverManager.getConnection(URL, USER, PASSWORD);
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return connection;
    }


    private static ResultSet select(String sql) {
        Connection conn = getConnection();
        ResultSet rs = null;
        try {
            Statement cs = conn.createStatement();
            rs = cs.executeQuery(sql);
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return rs;
    }


    public static Map<String, Object> getTableInfo(String tableName) {
        Map<String, Object> item = new LinkedHashMap<String, Object>();
        //mysql
        //获取字段信息sql
        String columnInfoSql = "select TABLE_NAME,COLUMN_NAME,DATA_TYPE,COLUMN_COMMENT,IS_NULLABLE,COLUMN_DEFAULT,COLUMN_KEY from information_schema.columns where table_schema='" + DATABASE + "' and TABLE_NAME='" + tableName + "'";
        //获取表信息sql
        String tableInfoSql = "SELECT TABLE_COMMENT FROM information_schema.TABLES WHERE table_schema='" + DATABASE + "' and TABLE_NAME='" + tableName + "'";
        ResultSet columnInfo = select(columnInfoSql);
        ResultSet tableInfo = select(tableInfoSql);
        try {
            while (tableInfo.next()) {
                String tableComment = tableInfo.getString("TABLE_COMMENT");
                item.put("tableComment", tableComment);
            }
            List<Map<String, Object>> clist = new ArrayList<Map<String, Object>>();
            int i = 1;
            while (columnInfo.next()) {
                Map<String, Object> citem = new LinkedHashMap<String, Object>();
                /** 字段名 */
                String columnName = columnInfo.getString("COLUMN_NAME");
                /** 字段描述 */
                String columnDesc = columnInfo.getString("COLUMN_COMMENT");
                String columnClsName = changeColumn(columnName);
                String columnType = changeDateType(columnInfo.getString("DATA_TYPE"));
                String columnClsType = changeClsType(columnType);
                String isNull = columnInfo.getString("IS_NULLABLE");
                //主键字段
                String primaryKey = columnInfo.getString("COLUMN_KEY");
                /** 字段名、Java类字段、字段描述、字段类型、Java类字段类型 */
                citem.put("columnName", columnName);
                citem.put("columnClsName", columnClsName);
                citem.put("columnDesc", columnDesc);
                citem.put("columnType", columnType);
                citem.put("columnClsType", columnClsType);
                citem.put("isNull", isNull);
                citem.put("curSize", i++);
                citem.put("primaryKey", primaryKey);
                clist.add(citem);
            }
            item.put("columnInfo", clist);
            item.put("columnSize", clist.size());
        } catch (Exception e) {
            e.printStackTrace();
        }
        item.put("tableName", tableName);
        item.put("clsName", changeClsName(tableName));
        item.put("curTime", getCurrTime());
        item.put("curDate", getCurrDate());
        //设置创建人和时间
        item.put("createUser", CREATE_USER);
        item.put("createTime", getCurrDate());
        return item;
    }

    public static String getCurrDate() {
        DateFormat df = new SimpleDateFormat("yyyy-MM-dd");
        return df.format(new java.util.Date());
    }

    public static String getCurrTime() {
        DateFormat df = new SimpleDateFormat("HH:mm:ss");
        return df.format(new java.util.Date());
    }

    private static String changeClsName(String tableName) {
        StringBuffer sb = new StringBuffer();
        String lowerCase = tableName.toLowerCase();
        boolean f = false;
        int i = 1;
        for (char c : lowerCase.toCharArray()) {
            int a = (int) c;
            if (a == 95) {
                f = true;
                i++;
                continue;
            }
            if (f || i == 1) {
                sb.append((c + "").toUpperCase());
                f = false;
            } else {
                sb.append(c);
            }
            i++;
        }
        return sb.toString();
    }

    private static String changeColumn(String str) {
        StringBuffer sb = new StringBuffer();
        String lowerCase = str.toLowerCase();
        boolean f = false;
        for (char c : lowerCase.toCharArray()) {
            int a = (int) c;
            if (a == 95) {
                f = true;
                continue;
            }
            if (f) {
                sb.append((c + "").toUpperCase());
                f = false;
            } else {
                sb.append(c);
            }
        }
        return sb.toString();
    }


    private static String changeDateType(String dataType) {

        if ("VARCHAR2".equalsIgnoreCase(dataType)) {
            return JdbcType.VARCHAR.name().toString();
        } else if ("CHAR".equalsIgnoreCase(dataType)) {
            return JdbcType.CHAR.name().toString();
        } else if ("NVARCHAR2".equalsIgnoreCase(dataType)) {
            return JdbcType.NVARCHAR.name().toString();
        } else if ("CLOB".equalsIgnoreCase(dataType)) {
            return JdbcType.CLOB.name().toString();
        } else if ("BLOB".equalsIgnoreCase(dataType)) {
            return JdbcType.BLOB.name().toString();
        } else if ("DATETIME".equalsIgnoreCase(dataType)) {
            return JdbcType.DATE.name().toString();
        } else if ("DATE".equalsIgnoreCase(dataType)) {
            return JdbcType.DATE.name().toString();
        } else if ("RAW".equalsIgnoreCase(dataType)) {
            return JdbcType.BLOB.name().toString();
        } else if ("LONG".equalsIgnoreCase(dataType)) {
            return JdbcType.BIGINT.name().toString();
        } else if ("NUMBER".equalsIgnoreCase(dataType)) {
            return JdbcType.NUMERIC.name().toString();
        } else if ("UROWID".equalsIgnoreCase(dataType)) {
            return JdbcType.BLOB.name().toString();
        } else {
            return "VARCHAR";
        }
    }


    private static String changeClsType(String dataType) {

        if (dataType.equalsIgnoreCase(JdbcType.VARCHAR.name().toString())) {
            return String.class.getSimpleName();
        } else if (dataType.equalsIgnoreCase(JdbcType.CHAR.name().toString())) {
            return String.class.getSimpleName();
        } else if (dataType.equalsIgnoreCase(JdbcType.CLOB.name().toString())) {
            return String.class.getSimpleName();
        } else if (dataType.equalsIgnoreCase(JdbcType.BLOB.name().toString())) {
            return String.class.getSimpleName();
        } else if (dataType.equalsIgnoreCase(JdbcType.DATE.name().toString())) {
            return Date.class.getSimpleName();
        } else if (dataType.equalsIgnoreCase(JdbcType.BLOB.name().toString())) {
            return String.class.getSimpleName();
        } else if (dataType.equalsIgnoreCase(JdbcType.BIGINT.name().toString())) {
            return Long.class.getSimpleName();
        } else if (dataType.equalsIgnoreCase(JdbcType.NUMERIC.name().toString())) {
            return BigDecimal.class.getSimpleName();
        } else {
            return String.class.getSimpleName();
        }
    }
}
